<!DOCTYPE html>
<meta charset="utf-8">
<title>Dynamic change to style containment</title>
<link rel="help" href="https://drafts.csswg.org/css-contain/#contain-property">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1765615">
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<meta name="assert" content="Verify style containment is properly updated after dynamic change to the contain property.">
<style>
  /* Selectors for contain */
  #none .wrapper {
      contain: none;
  }
  #style .wrapper {
      contain: style;
  }
  #none_to_style .wrapper {
      contain: none;
  }
  #style_to_none .wrapper {
      contain: style;
  }

  /* Selectors for testing counters */
  .set_counter_to_9 {
      counter-set: testcounter 9;
  }
  .increment_counter {
      counter-increment: testcounter;
  }
  .set_counter_to_10 {
      counter-set: testcounter 10;
  }
  span.print_counter::after {
      font: 25px/1 Ahem;
      content: counters(testcounter, ".");
  }

  /* Selectors for testing quotes */
  .open_quote::after {
      content: open-quote;
  }
  .close_quote::after {
      content: close-quote;
  }
  .no_open_quote::after {
      content: no-open-quote;
  }
  .no_close_quote::after {
      content: no-close-quote;
  }
  span.print_quotes::before, span.print_quotes::after {
      font: 25px/1 Ahem;
      quotes: "A" "" "BB" "" "CCC" "" "DDDD" "" "EEEEE" "" "FFFFF" "" "GGGGGG" "" "HHHHHHH" "" "IIIIIIII" "" "JJJJJJJJJ" "";
  }
  span.print_quotes::before {
      content: open-quote;
  }
  span.print_quotes::after {
      content: no-close-quote;
  }
</style>
<body>
  <div id="log"></div>

  <div id="none">
    <div class="set_counter_to_9"></div>
    <span><span class="print_counter"></span></span>
    <div class="wrapper">
      <span class="increment_counter"></span>
    </div>
    <span><span class="print_counter"></span></span>

    <div class="set_counter_to_9"></div>
    <span><span class="print_counter"></span></span>
    <div class="wrapper">
      <span class="set_counter_to_10"></span>
    </div>
    <span><span class="print_counter"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="open_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="close_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="no_open_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="no_close_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>
  </div>

  <div id="style">
    <div class="set_counter_to_9"></div>
    <span><span class="print_counter"></span></span>
    <div class="wrapper">
      <span class="increment_counter"></span>
    </div>
    <span><span class="print_counter"></span></span>

    <div class="set_counter_to_9"></div>
    <span><span class="print_counter"></span></span>
    <div class="wrapper">
      <span class="set_counter_to_10"></span>
    </div>
    <span><span class="print_counter"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="open_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="close_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="no_open_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="no_close_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>
  </div>

  <div id="none_to_style">
    <div class="set_counter_to_9"></div>
    <span><span class="print_counter"></span></span>
    <div class="wrapper">
      <span class="increment_counter"></span>
    </div>
    <span><span class="print_counter"></span></span>

    <div class="set_counter_to_9"></div>
    <span><span class="print_counter"></span></span>
    <div class="wrapper">
      <span class="set_counter_to_10"></span>
    </div>
    <span><span class="print_counter"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="open_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="close_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="no_open_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="no_close_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>
  </div>

  <div id="style_to_none">
    <div class="set_counter_to_9"></div>
    <span><span class="print_counter"></span></span>
    <div class="wrapper">
      <span class="increment_counter"></span>
    </div>
    <span><span class="print_counter"></span></span>

    <div class="set_counter_to_9"></div>
    <span><span class="print_counter"></span></span>
    <div class="wrapper">
      <span class="set_counter_to_10"></span>
    </div>
    <span><span class="print_counter"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="open_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="close_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="no_open_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>

    <span><span class="print_quotes"></span></span>
    <div class="wrapper">
      <span class="no_close_quote"></span>
    </div>
    <span><span class="print_quotes"></span></span>
  </div>

  <script>
    function verifyStyleContainment(id, applied) {
        let container = document.getElementById(id);

        // To verify style containment for counters and quotes, we check whether
        // the properties in the wrapper affect the string length of generated
        // content.
        function haveSameStringLength(box1, box2) {
            const ahemFontSizePx = 25;
            return Math.abs(box2.width - box1.width) < ahemFontSizePx / 2;
        }
        let counter_box =
            Array.from(container.getElementsByClassName("print_counter"))
            .map(e => e.parentNode.getBoundingClientRect());
        let quote_box =
            Array.from(container.getElementsByClassName("print_quotes"))
            .map(e => e.parentNode.getBoundingClientRect());
        assert_equals(haveSameStringLength(counter_box[0], counter_box[1]), applied, "increment-counter");
        assert_equals(haveSameStringLength(counter_box[2], counter_box[3]), applied, "set-counter");
        assert_equals(haveSameStringLength(quote_box[0], quote_box[1]), applied, "open-quote");
        assert_equals(haveSameStringLength(quote_box[2], quote_box[3]), applied, "close-quote");
        assert_equals(haveSameStringLength(quote_box[4], quote_box[5]), applied, "no-open-quote");
        assert_equals(haveSameStringLength(quote_box[6], quote_box[7]), applied, "no-close-quote");
    }

    function setContain(id, value) {
        let container = document.getElementById(id);
        Array.from(container.getElementsByClassName("wrapper"))
            .forEach(element => element.style.contain = value);
    }

    promise_test(async () => {
        await document.fonts.ready;
        verifyStyleContainment("none", /*applied=*/ false);
    }, "contain: none");

    promise_test(async () => {
        await document.fonts.ready;
        verifyStyleContainment("style", /*applied=*/ true);
    }, "contain: style");

    promise_test(async () => {
        await document.fonts.ready;
        setContain("none_to_style", "style");
        verifyStyleContainment("none_to_style", /*applied=*/ true);
    }, "switching contain from none to style");

    promise_test(async () => {
        await document.fonts.ready;
        setContain("style_to_none", "none");
        verifyStyleContainment("style_to_none", /*applied=*/ false);
    }, "switching contain from style to none");
  </script>
</body>
